﻿
var inConsole = (typeof(window)=='undefined');
/*if (inConsole) {
  var window = {};
}*/

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function Array_prototype_indexOf(elt /*, from*/) {
    var len = this.length >>> 0;
    var from = Number(arguments[1]) || 0;
    from = (from < 0)
      ? Math.ceil(from)
      : Math.floor(from);
    if (from < 0) {
      from += len;
    }
    for (; from < len; from++) {
      if (from in this && this[from] === elt) {
        return from;
      }
    }
    return -1;
  };
} else {
  var Array_prototype_indexOf = Array.prototype.indexOf
}

Array.prototype.has = function Array_prototype_has(item) {
  return Array_prototype_indexOf.call(this, item) !== -1;
}

Array.prototype.isArray = true;

String.prototype.times = function String_prototype_times(number) {
  var res = new Array(number);
  while (number--) {
    res[number] = this;
  }
  return ArrayJoin.call(res, '');
}

var functionNameExtractor = /^[\s\(]*function\s*([^(]*)\([^)]*\)/;

var ArrayToString = Array.prototype.toString;
var Array_prototype_join = Array.prototype.join;

var ArrayJoin = function(joiner) {
  return Array_prototype_join.call(this, typeof(joiner)!='undefined' ? joiner : ', ');
}
var iDepth = 0;
var indent = '  ';

var objsPrinting = [];

Object.prototype.toString = function Object_prototype_toString() {
  var isRootPrinter = false;
  if (objsPrinting.length) {
    if (objsPrinting.has(this)) {
      return '_#SHARP#_';
    } else {
      objsPrinting.push(this);
    }
  } else {
    isRootPrinter = true;
    objsPrinting.push(this);
  }
  if (typeof(this.length)!='undefined') {
    var result = this.length
      ? '( ' + ArrayJoin.call(this) + ' )'
      : '()';
    if (isRootPrinter) {
      objsPrinting = [];
    }
    return result;
  }
  var results = [], i = 0;
  iDepth++;
  for (var property in this) {
    if (this[property]!==Object.prototype.toString) {
      results[i] = i++ ? '\n' + indent.times(iDepth) + property + ': ' + this[property] : '{\n' + indent.times(iDepth) + property + ': ' + this[property];
    }
  }
  iDepth--;
  results[i-1] += '\n' + indent.times(iDepth) + '}';
  if (isRootPrinter) {
    objsPrinting = [];
  }
  return i ? ArrayJoin.call(results) : '{}';
}

Function.prototype.toString = (function() {
  var oldFunctionToString = Function.prototype.toString;
  
  return function newFunctionToString() {
    if (objsPrinting.length) { return '_function_'; }
    return oldFunctionToString.call(this).replace(/\n/g,'\n'+indent.times(iDepth));
  };
})();

function inspect(obj) {
  return Object.prototype.toString.call(obj);
}

function F__() { }

function Beget(parent, linkToPrototype) {
  F__.prototype = parent;
  if (linkToPrototype) {
    var obj = new F__();
    obj.__prototype__ = parent;
    return obj;
  } else {
    return new F__();
  }
}

var Module = (function ModuleSystem() {

  var _modules = {};

  function Module(moduleImporter, defaultImport) {
    var fullName = moduleImporter.toString().match(functionNameExtractor)[1].split('__').join('.');
    var module = _modules[fullName] = {
      importer: moduleImporter
    , fullName: fullName
    , namePaths: fullName.split('.')
    , isDefaultImport: defaultImport ? true : false
    , Parse: function parseUsingModule(inputString) {
        
      }
    };
    if (module.isDefaultImport) {
      defaultBaseModules.push(module.fullName);
    }
    return module;
  }
  Module.Exec = function justRunTheFunction(functionAsModule) {
    var moduleContext = new ModuleContext();
    functionAsModule(moduleContext);
  };
  
  var defaultBaseModules = [];

  var currentlyImporting = {};

  var importHasRoot = false;

  function ModuleContext(dontRecurse) {
    this.__members = [];
    this.__toLinkFrom = [];
    if (!dontRecurse) {
      for (var i = 0; i < defaultBaseModules.length; i++) {
        this.Import(defaultBaseModules[i], "dontRecurse");
      }
    }
  }
  ModuleContext.prototype = {
    Import: function moduleImporter(nameOfModuleToImport, dontRecurse) {
      var isRoot = false;
      if (!importHasRoot) {
        isRoot = importHasRoot = true;
        currentlyImporting = {};
      }
      var newContext = new ModuleContext(dontRecurse);
      if (currentlyImporting[nameOfModuleToImport]) {
        this[nameOfModuleToImport] = currentlyImporting[nameOfModuleToImport];
      } else {
        currentlyImporting[nameOfModuleToImport] = newContext;
        _modules[nameOfModuleToImport].importer(newContext);
        newContext.__private = Beget(newContext);
        for (var i = 0; i < newContext.__members.length; i++) {
          var memberContext = Beget(newContext);
          newContext.__members[i].importer(memberContext);
          if (newContext.__members[i].exported) {
            newContext[newContext.__members[i].name] = memberContext;
          }
          newContext.__private[newContext.__members[i].name] = memberContext;
        }
        var i = _modules[nameOfModuleToImport].namePaths.length;
        var j = i, parent, path;
        (parent = this)[_modules[nameOfModuleToImport].namePaths[i-1]] = newContext;
        while (--j+1) {
          parent = parent[path = _modules[nameOfModuleToImport].namePaths[i-j-1]] = j
            ? parent[path] || {}
            : newContext;
        }
      }
      if (isRoot) {
        importHasRoot = false;
      }
    },
    Language: function declareLanguage(memberImporter) {
      var memberName = memberImporter.toString().match(functionNameExtractor)[1].split('__').join('.');
      var member = {
        name: memberName
      , importer: memberImporter
      , exported: false
      , Export: function() {
          this.exported = !this.exported;
        }
      };
      this.__members.push(member);
      return member;
    }
  };
  return Module;
})();


Module(function Common1(l) {
  l.Language(function Base(l) {
    l.baz = function(){ return "baz" };
  }).Export();
}, true);

Module(function e1__e22(l) {
  l.Import('e1.e11');
  l.Language(function foo(l) { with (l.__private) {
    l.Main = function(){ return "e22foo " + Common1.Base.baz() };
  }}).Export();
});


Module(function e1__e11(l) {
  l.Import('e1.e22');
  l.Language(function foo(l) { with (l.__private) {
    l.Main = function(){ return "foo " + Common1.Base.baz() + ' ' + bar.Main() };
  }}).Export();
  l.Language(function bar(l) { with (l.__private) {
    l.Main = function(){ return "bar " + blip.blah() + ' ' + e1.e22.foo.Main() };
  }}).Export();
  l.Language(function blip(l) { with (l.__private) {
    l.blah = function(){ return "blip.blah" };
  }});
});

Module.Exec(function runit(l) { with (l) {
  l.Import('e1.e11');
  l.baf = function(){ return "baf" };
  print(baf());
  print(e11.foo.Main());
  print(e1.e11.bar.Main());
}});











